package com.xinqi.modules.sys.gpt.service.impl;

import com.baomidou.dynamic.datasource.annotation.DS;
import com.xinqi.common.base.error.CommonErrors;
import com.xinqi.common.base.response.PageInfo;
import com.xinqi.common.base.response.Param;
import com.xinqi.common.base.response.R;
import com.xinqi.common.base.utils.spring.Spring;
import com.xinqi.common.core.constant.CacheConstants;
import com.xinqi.common.core.constant.ChatRemindConstants;
import com.xinqi.common.core.constant.ConfigKeyConstants;
import com.xinqi.common.core.constant.GptConstants;
import com.xinqi.common.core.enums.ChatRemindTypeEnum;
import com.xinqi.common.core.enums.RegisterRoleEnum;
import com.xinqi.common.core.utils.MessageUtils;
import com.xinqi.common.core.utils.PlaceholderUtils;
import com.xinqi.common.mybatis.utils.Pages;
import com.xinqi.common.redis.utils.RedisUtils;
import com.xinqi.modules.chat.chat.group.dto.rsp.ShareSelectResultDTO;
import com.xinqi.modules.chat.chat.official.client.ChatRemindContentClient;
import com.xinqi.modules.chat.chat.official.dto.req.ChatRemindContentCreateDTO;
import com.xinqi.modules.chat.chat.rongyun.RemoteRongyunClient;
import com.xinqi.modules.course.course.client.RemoteCourseClient;
import com.xinqi.modules.sys.config.service.ISysConfigService;
import com.xinqi.modules.sys.gpt.domain.DayCountEntity;
import com.xinqi.modules.sys.gpt.domain.ShareLogEntity;
import com.xinqi.modules.sys.gpt.domain.ShareQuotaEntity;
import com.xinqi.modules.sys.gpt.dto.req.ShareLogQueryDTO;
import com.xinqi.modules.sys.gpt.dto.rsp.ShareLogResultDTO;
import com.xinqi.modules.sys.gpt.manager.DayCountManager;
import com.xinqi.modules.sys.gpt.manager.ShareLogManager;
import com.xinqi.modules.sys.gpt.manager.ShareQuotaManager;
import com.xinqi.modules.sys.gpt.service.ShareLogService;
import com.xinqi.modules.user.user.client.UserClient;
import com.xinqi.modules.user.user.dto.req.UserRegisterDTO;
import com.xinqi.modules.user.user.dto.req.UserShareRegisterDTO;
import com.xinqi.modules.user.user.dto.rsp.UserResultDTO;
import lombok.RequiredArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Objects;

/**
 * 用户分享注册记录服务层实现
 *
 * @author: yyzhen
 * @date: 2023/05/23
 */
@Validated
@Service("shareLogService")
@RequiredArgsConstructor
public class ShareLogServiceImpl implements ShareLogService {

    private final ShareLogManager shareLogManager;

    private final DayCountManager dayCountManager;

    private final ShareQuotaManager shareQuotaManager;

    private final ISysConfigService sysConfigService;

    private final ChatRemindContentClient remindContentClient;

    private final RemoteCourseClient remoteCourseClient;

    private final RemoteRongyunClient rongyunClient;

    private final UserClient userClient;

    /**
     * 分页查询 用户分享注册记录数据
     */
    @Override
    @DS("slaver")
    public PageInfo<ShareLogResultDTO> page(Param pageable, ShareLogQueryDTO query) {
        //添加排序
        pageable.setSorts(new ArrayList<>());
        pageable.getSorts().add("l.register_time,desc");
        return Pages.convert(shareLogManager.findPage(Pages.page(pageable), query));
    }

    /**
     * 分享邀请链接
     *
     * @param userId
     * @return
     */
    @Override
    public ShareSelectResultDTO getSharePersonalInfo(Long userId) {
        UserResultDTO user = R.as(userClient.findById(userId));
        CommonErrors.BAD_REQUEST.check(Objects.nonNull(user), MessageUtils.message("user.is.not.existence"));

        //获取连接地址
        String shareUrl = sysConfigService.selectConfigByKey(ConfigKeyConstants.CHAT_GPT_SHARE_URL);
        //获取token
        String logo = sysConfigService.selectConfigByKey(ConfigKeyConstants.SYS_DEFAULT_LOGO);

        ShareSelectResultDTO share = new ShareSelectResultDTO();
        share.setUserId(user.getId());
        share.setAvatar(user.getAvatar());
        share.setNickname(user.getNickname());
        share.setXinqiNumber(user.getXinqiNumber());
        share.setContent(GptConstants.CONTENT);
        share.setLogo(logo);
        share.setTitle(PlaceholderUtils.replaceWithVarargs(GptConstants.TITLE, user.getNickname()));
        share.setUrl(shareUrl + PlaceholderUtils.replaceWithVarargs(GptConstants.URL, user.getId().toString(), user.getNickname(), user.getAvatar()));
        return share;
    }

    /**
     * 邀请链接 -- 手机号、验证码注册，
     * 注册成功则邀请人获得相关奖励
     * 返回注册人信息
     *
     * @param dto :
     * @return :com.xinqi.modules.sys.user.user.dto.rsp.UserResultDTO
     * @Title:
     * @MethodName: shareRegister
     * @Exception
     * @Description:
     * @author: yyzhen
     * @date: 2023/5/23 16:15
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public UserResultDTO shareRegister(UserShareRegisterDTO dto) {
        //手机验证码校验
        CommonErrors.BAD_REQUEST.check(validateSmsCode(dto.getMobile(), dto.getSmsCode()), MessageUtils.message("gpt.share.register.code.invalid"));
        //手机号校验
        UserResultDTO user = R.as(userClient.findByMobile(dto.getMobile()));
        CommonErrors.BAD_REQUEST.check(Objects.isNull(user), MessageUtils.message("gpt.share.register.mobile.existence"));
        //校验手机号码是否为新用户
        Boolean isNew = R.as(userClient.findByMobileIncludeDelete(dto.getMobile()));
        //手机号注册
        UserRegisterDTO registerDto = new UserRegisterDTO();
        registerDto.setMobile(dto.getMobile());
        registerDto.setSmsCode(dto.getSmsCode());
        registerDto.setNickName(initNickname(dto.getMobile()));
        registerDto.setSchoolName("未知");
        registerDto.setPassword(dto.getPassword());
        registerDto.setUserRole(dto.getUserRole());
        UserResultDTO register = R.as(userClient.register(registerDto));
        CommonErrors.BAD_REQUEST.check(Objects.nonNull(register), MessageUtils.message("gpt.share.register.mobile.existence"));
        //获取分享人信息
        UserResultDTO share = R.as(userClient.findById(dto.getUserId()));
        LocalDateTime now = LocalDateTime.now();

        if (Objects.nonNull(share) && isNew) {
            //记录邀请用户日志
            ShareLogEntity logEntity = new ShareLogEntity();
            logEntity.setUserId(share.getId());
            logEntity.setInvitedUserId(register.getId());
            logEntity.setRegisterTime(now);
            shareLogManager.save(logEntity);
            //邀请成功增加次数
            DayCountEntity countEntity = dayCountManager.findByUserAndInit(share.getId());
            //获取今日邀请成功次数
            int shareCount = countEntity.getShareCount() + 1;
            //获取今日可用次数
            int availableCount = countEntity.getAvailableCount();
            //计算最终今日可用次数
            if (availableCount < GptConstants.DEFAULT_MAX_QUOTA) {
                //获取邀请成功增加的配置
                ShareQuotaEntity quotaEntity = shareQuotaManager.findByCount(shareCount);
                //获取邀请成功获得次数
                int shareQuota = 0;
                if (Objects.isNull(quotaEntity) || Objects.isNull(quotaEntity.getShareQuota()) || Objects.equals(0, quotaEntity.getShareQuota())) {
                    shareQuota = GptConstants.DEFAULT_SHARE_QUOTA;
                } else {
                    shareQuota = quotaEntity.getShareQuota();
                }
                availableCount = availableCount + shareQuota;
                if (availableCount > GptConstants.DEFAULT_MAX_QUOTA) {
                    //超过每日上限则为每日上限
                    availableCount = GptConstants.DEFAULT_MAX_QUOTA;
                }
            }
            countEntity.setShareCount(shareCount);
            countEntity.setAvailableCount(availableCount);
            dayCountManager.updateById(countEntity);
        }
        //新奇提醒机器人 -- 首次进入
        remindContentClient.insert(new ChatRemindContentCreateDTO(register.getId(), ChatRemindTypeEnum.FIRST_ENTRY, ChatRemindConstants.REMIND_FIRST_ENTRY_TEMPLATE));
        Spring.committed(() -> {
            // 同步示范课程
            if (Objects.equals(RegisterRoleEnum.TEACHER.getCode(), register.getUserRole())) {
                remoteCourseClient.initDemonstrate(register.getId());
            }
            rongyunClient.updateUser(register.getId().toString(), register.getNickname(), register.getAvatar());
        });
        return register;

    }

    /**
     * 获取某天用户的邀请数量
     *
     * @param userId
     * @param day
     * @return
     */
    @Override
    public int countByDay(Long userId, LocalDateTime day) {
        return shareLogManager.countByDay(userId, day);
    }

    /**
     * 初始化用户昵称
     *
     * @return
     */
    private String initNickname(String mobile) {
        //查看邀请注册总人数
        //long count = shareLogManager.count();
        //昵称，新奇000000001依次递增
        // return "新奇" + String.format("%09d", (count + 1));
        return "新奇" + mobile;
    }

    /**
     * 验证码校验
     *
     * @param mobile
     * @param smsCode
     * @return
     */
    private boolean validateSmsCode(String mobile, String smsCode) {
        if (StringUtils.isEmpty(smsCode)) {
            return false;
        }
        if (StringUtils.isEmpty(mobile)) {
            return false;
        }
        String code = RedisUtils.getCacheObject(CacheConstants.CAPTCHA_CODE_KEY + mobile);
        return Objects.equals(code, smsCode);
    }


}
